package com.example.kingdeescan.ui.search;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;
import android.util.SparseBooleanArray;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.SearchView;
import android.widget.TextView;
import android.widget.Toast;

import com.example.kingdeescan.MainActivity;
import com.example.kingdeescan.R;
import com.example.kingdeescan.R2;
import com.example.kingdeescan.adapter.SelBillNoResultAdapter;
import com.example.kingdeescan.dao.FBiller;
import com.example.kingdeescan.dao.FDept;
import com.example.kingdeescan.dao.FEmp;
import com.example.kingdeescan.dao.FFManger;
import com.example.kingdeescan.dao.FOrg;
import com.example.kingdeescan.dao.SEOutStock;
import com.example.kingdeescan.enums.DocType;
import com.example.kingdeescan.enums.MessageType;
import com.example.kingdeescan.enums.SearchType;

import java.io.Serializable;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.Unbinder;
import lombok.SneakyThrows;

import static com.example.kingdeescan.MainActivity.dbConfig;
import static com.example.kingdeescan.MainActivity.dbUtil;
import static com.example.kingdeescan.MainActivity.docInfoDTO;
import static com.example.kingdeescan.MainActivity.fragmentService;

/**
 * @author  : 2020/7/24
 * @date    : zly
 * @desc    : 搜索Fragment
 */
public class SearchFragment extends Fragment implements SearchView.OnQueryTextListener,
        AdapterView.OnItemClickListener,View.OnClickListener {

    public static final String TAG="SearchFragment";
    private SearchViewModel searchViewModel;

    @BindView(R2.id.search_view)
    SearchView searchView;//统一搜索框
    @BindView(R2.id.lv_search_view_result)
    ListView listView;//搜索结果列表
    @BindView(R2.id.btn_search_view_commit)
    Button btn_search_view_commit;//确定按钮
    @BindView(R.id.ll_search_selbillno_head)
    LinearLayout ll_search_selbillno_head;//选单号的表头行

    private ArrayAdapter<?> adapter;//listView的适配器
    private List<String>  fSearchResultList;//存储查询结果集合
    private List<?> queryResultList = null;//泛型集合存储查询结果

    SelBillNoResultAdapter selBillNoResultAdapter;//选单号适配器
    List<SEOutStock> seOutStockList=new ArrayList<>();//存储查询的选单号
    List<SEOutStock> seOutStockCheckedList;//存储选中的选单号

    //用来存放CheckBox的选中状态，true为选中,false为没有选中.(存储形式为键值对)
    private SparseBooleanArray stateCheckedMap;

    private int searchType;//存储当前搜索类型

    FEmp fEmp;//业务员
    FDept fDept;//部门
    FFManger ffManger;//发货员
    FOrg fOrg;//购货单位
    FOrg fSelBillNoFOrg;//选单号购货单位
    FBiller fBiller;//制单员

    Unbinder unbinder;//绑定ButterKnife视图
    Bundle sendBundle;

    View root;
    ViewGroup container;

    //处理消息Handler
    Handler searchHandler=new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);

            switch (msg.what)
            {
                case MessageType.MESSAGE_SEARCH:
                    adapter.notifyDataSetChanged();//刷新适配器(刷新列表)
                    break;
                case MessageType.MESSAGE_SEARCH_SET_SELBILLNO_ADAPTER:
                    if (null!=ll_search_selbillno_head){
                        ll_search_selbillno_head.setVisibility(View.VISIBLE);
                        listView.setAdapter(selBillNoResultAdapter);
                    }
                    break;
                case MessageType.MESSAGE_SEARCH_SET_COMMON_ADAPTER:
                    if (null!=listView){
                        listView.setAdapter(adapter);
                    }
                    break;
            }
        }
    };

    /**
     * 设置SearchFragment相关接口
     * 声明了一个内部接口，来回调其点击事件，想要 管理其点击事件的Activity实现此接口就即可
     */
    public interface FSearchListener{
        void onFSearchCommitClick(View v,Bundle bundle);//确认按钮点击回调
        void onFSearchNonEvent(View v);//搜索为空回调
    }

    public View onCreateView(@NonNull LayoutInflater inflater,
                             ViewGroup container, Bundle savedInstanceState) {
        root = inflater.inflate(R.layout.fragment_search, container, false);
        //返回一个Unbinder值（进行解绑），注意这里的this不能使用getActivity()
        unbinder = ButterKnife.bind(this, root);

        //获取Bundle传输数据,根据传输的查询类型，响应不同的布局和数据
        int searchType = getBundle();
        boolean invalidSearchType = fragmentService.validSearchType(getActivity(), container, this, searchType);
        if (!invalidSearchType) {
            return null;
        }
        //存储当前搜索类型
        this.searchType =searchType;
        //存储当前容器视图
        this.container=container;
        try {
            initComponet();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return root;
    }

    /**
     * 初始化组件
     */
    @SneakyThrows
    private void initComponet() {
        connSqlByThread();//初始化时连接数据库，避免重复连接(使用多线程处理，避免堵塞主线程)
        initConfig();//初始化搜索框的配置
        dynamicSearchTypeComponent(this.container);//初始化数据和适配器
    }

    /**
     * 初始化各控件的配置
     */
    private void initConfig(){
        //搜索图标是否显示在搜索框内
        searchView.setIconifiedByDefault(true);
        //设置搜索框展开时是否显示提交按钮，可不显示
        searchView.setSubmitButtonEnabled(false);
        //让键盘的回车键设置成搜索
        searchView.setImeOptions(EditorInfo.IME_ACTION_SEARCH);
        //搜索框是否展开，false表示展开
        searchView.setIconified(false);
        //获取焦点
        searchView.setFocusable(true);
        searchView.requestFocusFromTouch();
        //搜索框添加查询文本监听器
        searchView.setOnQueryTextListener(this);

        int id = searchView.getContext().getResources().getIdentifier("android:id/search_src_text",null,null);
        //获取到TextView的控件
        TextView tv_SearchView = searchView.findViewById(id);
        //设置字体大小为14sp
        tv_SearchView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14);//14sp
        tv_SearchView.setAlpha(0.8f);
        //设置字体颜色
        tv_SearchView.setTextColor(getActivity().getResources().getColor(R.color.colorPrimary));
        //设置提示文字颜色
//        tv_SearchView.setHintTextColor(getActivity().getResources().getColor(R.color.design_default_color_primary));

        //确定按钮的监听器
        btn_search_view_commit.setOnClickListener(this);

        //设置listView的子项点击监听事件
        listView.setOnItemClickListener(this);
    }

    /**
     * 根据当前搜索类型，响应不同的控件，加载数据和适配器
     */
    private void dynamicSearchTypeComponent(ViewGroup container) {
        if (docInfoDTO.getDocType()== DocType.DOC_TYPE_SSCK){
            if (this.searchType==SearchType.SEARCH_FSELBILLNO_TYPE){
                if (null==this.fSelBillNoFOrg){
                    Toast.makeText(getContext(), "选单号加载失败!", Toast.LENGTH_SHORT).show();
                    if (getActivity() instanceof FSearchListener)
                    {
                        ((FSearchListener) getActivity()).onFSearchNonEvent(container);
                    }
                }else{
                    getSelBillNoInfo(container,this.fSelBillNoFOrg);//获取选单信息
                }
            }else{
                //初始化查询结果集合
                fSearchResultList=new ArrayList<>();
                //创建适配器，传入参数
                adapter=new ArrayAdapter<>(getContext(),android.R.layout.simple_list_item_1, fSearchResultList);

                Message message=new Message();
                message.what=MessageType.MESSAGE_SEARCH_SET_COMMON_ADAPTER;
                searchHandler.sendMessage(message);
            }
        }
    }

    /**
     * 获取选单信息并加载到适配器中
     * @param container
     * @param fSelBillNoFOrg
     */
    @SneakyThrows
    private void getSelBillNoInfo(ViewGroup container,FOrg fSelBillNoFOrg){
        Thread mThread=new Thread(() -> {
            try {
                seOutStockList = dbUtil.querySelBillNo(fSelBillNoFOrg.getFItemID());
                Log.d(TAG, "selectedList.size: "+seOutStockList.size());

                if (null!=seOutStockList && seOutStockList.size()>0){
                    stateCheckedMap = new SparseBooleanArray();
                    seOutStockCheckedList=new ArrayList<>();

                    selBillNoResultAdapter=new SelBillNoResultAdapter(getContext(),R.layout.fragment_search_sellbillno, seOutStockList,stateCheckedMap);
                    Message message=new Message();
                    message.what=MessageType.MESSAGE_SEARCH_SET_SELBILLNO_ADAPTER;
                    searchHandler.sendMessage(message);
                }else{
                    Toast.makeText(getContext(), "当前购货单位暂无选单信息!", Toast.LENGTH_SHORT).show();
                    //当前客户单位暂无选单号信息，返回必录项页面并提示
                    if (getActivity() instanceof FSearchListener)
                    {
                        ((FSearchListener) getActivity()).onFSearchNonEvent(container);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
        mThread.start();
    }

    /**
     * 获取选单信息并加载到适配器中(模糊查询)
     * @param fSelBillNoFOrg
     * @param queryText
     */
    @SneakyThrows
    private void getSelBillNoInfo(FOrg fSelBillNoFOrg,String queryText){
        Thread mThread=new Thread(() -> {
            try {
                seOutStockList = dbUtil.querySelBillNo(fSelBillNoFOrg.getFItemID(),queryText);
                Log.d(TAG, "selectedList.size: "+seOutStockList.size());

                if (null!=seOutStockList && seOutStockList.size()>0){
                    stateCheckedMap = new SparseBooleanArray();
                    seOutStockCheckedList=new ArrayList<>();
                }else{
                    seOutStockList.clear();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }finally {
                selBillNoResultAdapter=new SelBillNoResultAdapter(getContext(),R.layout.fragment_search_sellbillno, seOutStockList,stateCheckedMap);
                Message message=new Message();
                message.what=MessageType.MESSAGE_SEARCH_SET_SELBILLNO_ADAPTER;
                searchHandler.sendMessage(message);
            }
        });
        mThread.start();
    }

    /**
     * 初始化时连接数据库，避免重复连接(使用多线程处理，避免堵塞主线程)
     * @throws SQLException
     */
    private void connSqlByThread() throws SQLException {
        if (!dbUtil.isConnOpened() && null!=dbConfig){
            new Thread(() -> {
                try {
                    dbUtil.getDBConn(dbConfig);//连接数据库
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }

    /**
     * 获取Bundle传输数据
     * @return
     *      0:Bundle传递数据为空
     *      其他:对应的SearchType的值
     */
    private int getBundle(){
        Bundle bundle = getArguments();
        if (null==bundle){
            return 0;
        }
        Serializable serializable;//存储序列化对象数据
        int searchType = bundle.getInt("SearchType");
        switch (searchType){
            case SearchType.SEARCH_FORG_TYPE:
                serializable = bundle.getSerializable("RecoredFOrg");
                if (null!=serializable){
                    fOrg=new FOrg();
                    fOrg= (FOrg) serializable;
                }
                break;
            case SearchType.SEARCH_FSELBILLNO_TYPE:
                serializable = bundle.getSerializable("RecoredFSelBillNoFOrg");
                if (null!=serializable){
                    fSelBillNoFOrg=new FOrg();
                    fSelBillNoFOrg= (FOrg) serializable;
                }
                break;
            case SearchType.SEARCH_FDEPT_TYPE:
                serializable = bundle.getSerializable("RecoredFDept");
                if (null!=serializable){
                    fDept=new FDept();
                    fDept= (FDept) serializable;
                }
                break;
            case SearchType.SEARCH_FEMP_TYPE:
                serializable = bundle.getSerializable("RecoredFEmp");
                if (null!=serializable){
                    fEmp=new FEmp();
                    fEmp= (FEmp) serializable;
                }
                break;
            case SearchType.SEARCH_FFMANGER_TYPE:
                serializable = bundle.getSerializable("RecoredFFManger");
                if (null!=serializable){
                    ffManger=new FFManger();
                    ffManger= (FFManger) serializable;
                }
                break;
            case SearchType.SEARCH_FBILLER_TYPE:
                serializable = bundle.getSerializable("RecoredFBiller");
                if (null!=serializable){
                    fBiller=new FBiller();
                    fBiller= (FBiller) serializable;
                }
                break;
        }

        return searchType;
    }

    /**
     * 查询文本提交
     * @param query
     * @return
     */
    @Override
    public boolean onQueryTextSubmit(String query) {
        if (!queryBySearchType(query)){
            return false;
        }
        return true;
    }

    /**
     * 查询文本改变
     * @param newText
     * @return
     */
    @Override
    public boolean onQueryTextChange(String newText) {
        if (!queryBySearchType(newText)){
            return false;
        }
        return true;
    }

    /**
     * 判断查询内容是否为空
     * @param queryText
     * @return
     */
    private boolean isEmptyQueryTextAndMessage(String queryText){
        //没有父传递
        if (0==searchType){
            return false;
        }
        //选单号
        if (this.searchType==SearchType.SEARCH_FSELBILLNO_TYPE){
            if (TextUtils.isEmpty(queryText)) {
                getSelBillNoInfo(this.container,this.fSelBillNoFOrg);//获取选单信息
                return false;
            }
            return true;
        }else{
            //当查询文本为空，清空列表
            if (TextUtils.isEmpty(queryText)){
                fSearchResultList.clear();

                Message msg = new Message();
                msg.what=MessageType.MESSAGE_SEARCH;
                searchHandler.sendMessage(msg);
                return false;
            }
            return true;
        }
    }

    /**
     * 根据关键字和搜索类型搜索内容
     * @param queryText
     * @return
     */
    private boolean queryBySearchType(String queryText){
        //判断查询内容是否为空
        if (!isEmptyQueryTextAndMessage(queryText)){
            return false;
        }
        switch (searchType){
            case SearchType.SEARCH_FORG_TYPE://购货单位
                queryFOrg(queryText);
                break;
            case SearchType.SEARCH_FSELBILLNO_TYPE://选单号
                queryFSelbillno(queryText);
                break;
            case SearchType.SEARCH_FDEPT_TYPE://部门
                queryFDept(queryText);
                break;
            case SearchType.SEARCH_FEMP_TYPE://业务员
                queryFEmp(queryText);
                break;
            case SearchType.SEARCH_FFMANGER_TYPE://发货员
                queryFFManger(queryText);
                break;
            case SearchType.SEARCH_FBILLER_TYPE://制单员
                queryFBiller(queryText);
                break;
        }

        return true;
    }

    /**
     * 根据文本内容查询制单员(耗时操作，用多线程)
     * @param queryText
     */
    private void queryFBiller(String queryText) {
        queryCommonData(queryText, new FBiller());
    }

    /**
     * 根据文本内容查询发货员(耗时操作，用多线程)
     * @param queryText
     */
    private void queryFFManger(String queryText) {
        queryCommonData(queryText, new FFManger());
    }

    /**
     * 根据文本内容查询业务员(耗时操作，用多线程)
     * @param queryText
     */
    private void queryFEmp(String queryText) {
        queryCommonData(queryText, new FEmp());
    }

    /**
     * 根据文本内容查询部门(耗时操作，用多线程)
     * @param queryText
     */
    private void queryFDept(String queryText) {
        queryCommonData(queryText, new FDept());
    }

    /**
     * 根据文本内容查询供应商(耗时操作，用多线程)
     * @param queryText
     */
    private void queryFOrg(final String queryText){
        queryCommonData(queryText, new FOrg());
    }

    /**
     * 根据文本内容查询选单号(耗时操作，用多线程)
     * @param queryText
     */
    private void queryFSelbillno(String queryText) {
        getSelBillNoInfo(this.fSelBillNoFOrg,queryText);
    }

    /**
     * 自定义搜索内容
     * @param queryText
     *      查询关键字
     * @param t
     *      已知通配符类型，实现自动判定并查询
     * @param <T>
     */
    @SneakyThrows
    private <T> void queryCommonData(String queryText, T t){
        new Thread(() -> {
            try {
                //判断类型
                if (t instanceof FEmp){
                    queryResultList= dbUtil.queryFEmp(queryText);
                }
                if (t instanceof FOrg){
                    queryResultList= dbUtil.queryFOrg(queryText);
                }
                if (t instanceof FDept){
                    queryResultList= dbUtil.queryFDept(queryText);
                }
                if (t instanceof FFManger){
                    queryResultList= dbUtil.queryFFManger(queryText);
                }
                if (t instanceof FBiller){
                    queryResultList= dbUtil.queryFBiller(queryText);
                }
                //若查询成功，添加数据
                if (null!=queryResultList && queryResultList.size()>0){
                    fSearchResultList.clear();//刷新列表
                    //遍历查询结果集
                    for (int i = 0; i < queryResultList.size(); i++) {
                        Object o = queryResultList.get(i);
                        //添加数据
                        switch (searchType){
                            case SearchType.SEARCH_FORG_TYPE:
                                FOrg fOrg = (FOrg) o;
                                fSearchResultList.add(fOrg.getFName());
                                break;
//                            case SearchType.SEARCH_FSELBILLNO_TYPE:
//                                break;
                            case SearchType.SEARCH_FDEPT_TYPE:
                                FDept fDept= (FDept) o;
                                fSearchResultList.add(fDept.getFName());
                                break;
                            case SearchType.SEARCH_FEMP_TYPE:
                                FEmp fEmp= (FEmp) o;
                                fSearchResultList.add(fEmp.getFName());
                                break;
                            case SearchType.SEARCH_FFMANGER_TYPE:
                                FFManger ffManger= (FFManger) o;
                                fSearchResultList.add(ffManger.getFName());
                                break;
                            case SearchType.SEARCH_FBILLER_TYPE:
                                FBiller fBiller= (FBiller) o;
                                fSearchResultList.add(fBiller.getFName());
                                break;
                        }
                    }
                }else{
                    fSearchResultList.clear();
                }
            } catch (Exception e) {
                e.printStackTrace();
                fSearchResultList.clear();
            }finally {
                Message msg = new Message();
                msg.what=MessageType.MESSAGE_SEARCH;
                searchHandler.sendMessage(msg);
            }
        }).start();
    }

    /**
     * 查询列表子项点击
     * @param parent
     * @param view
     * @param position
     * @param id
     */
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        if (this.searchType==SearchType.SEARCH_FSELBILLNO_TYPE){
            //需判断当前选中项的勾选状态，如果为勾选，则取消勾选；如果为未勾选，则勾选(selectedList)
            //根据当前选中项的勾选状态，添加或移除数据对象(seOutStockCheckedList)
            updateCheckBoxStatus(view,position);
            return;
        }else{
            Object o = queryResultList.get(position);
            sendBundle=new Bundle();
            switch (this.searchType){
                case SearchType.SEARCH_FORG_TYPE:
                    FOrg fOrg = (FOrg) o;
                    sendBundle.putSerializable("SearchFOrg",fOrg);
                    break;
//                case SearchType.SEARCH_FSELBILLNO_TYPE:
//                    break;
                case SearchType.SEARCH_FDEPT_TYPE:
                    FDept fDept = (FDept) o;
                    sendBundle.putSerializable("SearchFDept",fDept);
                    break;
                case SearchType.SEARCH_FEMP_TYPE:
                    FEmp fEmp = (FEmp) o;
                    sendBundle.putSerializable("SearchFEmp",fEmp);
                    break;
                case SearchType.SEARCH_FFMANGER_TYPE:
                    FFManger ffManger = (FFManger) o;
                    sendBundle.putSerializable("SearchFFManger",ffManger);
                    break;
                case SearchType.SEARCH_FBILLER_TYPE:
                    FBiller fBiller = (FBiller) o;
                    sendBundle.putSerializable("SearchFBiller",fBiller);
                    break;
            }
            CharSequence item = fSearchResultList.get(position);
            searchView.setQuery(item,true);//将查询结果显示到搜索框上
            //获取焦点
            searchView.setFocusable(false);
        }
    }

    /**
     * 更改CheckBox状态,并根据该状态添加或移除数据对象
     * @param view
     * @param position
     */
    private void updateCheckBoxStatus(View view, int position) {
        SelBillNoResultAdapter.ViewHolderInner holder = (SelBillNoResultAdapter.ViewHolderInner) view.getTag();
        holder.checkBox.toggle();//反转CheckBox的选中状态
        stateCheckedMap.put(position, holder.checkBox.isChecked());//存放CheckBox的选中状态
        if (holder.checkBox.isChecked()) {
            seOutStockCheckedList.add(seOutStockList.get(position));//CheckBox选中时，把这一项的数据加到选中数据列表
        } else {
            seOutStockCheckedList.remove(seOutStockList.get(position));//CheckBox未选中时，把这一项的数据从选中数据列表移除
        }
        selBillNoResultAdapter.notifyDataSetChanged();
    }

    /**
     * 点击事件监听器
     * @param v
     */
    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.btn_search_view_commit://确认按钮
                //选单号
                if (this.searchType==SearchType.SEARCH_FSELBILLNO_TYPE){
                    //判断是否选中数据
                    if (null==seOutStockCheckedList || seOutStockCheckedList.size()<=0){
                        Toast.makeText(getContext(),"请选中选单号信息！",Toast.LENGTH_SHORT).show();
                        break;
                    }
                    //将选中单号数据对象传输 ,当传递对象时，需实现Serializeable序列化接口
                    sendBundle=new Bundle();
                    sendBundle.putSerializable("SelBillNoCheckedList", (Serializable) seOutStockCheckedList);
                    //判断了当前绑定的Activity是否实现了该接口，如果实现了 则调用
                    if (getActivity() instanceof FSearchListener)
                    {
                        ((FSearchListener) getActivity()).onFSearchCommitClick(v,sendBundle);
                    }
                    break;
                }else{
                    CharSequence query = searchView.getQuery();
                    //如果查询关键字为空则提示
                    if (TextUtils.isEmpty(query)){
                        Toast.makeText(getContext(),"请输入有效查询关键字！",Toast.LENGTH_SHORT).show();
                        break;
                    }
                    //如果用户没有输入有效查询内容则提示
                    if (null==queryResultList){
                        Toast.makeText(getContext(),"请输入有效查询关键字！",Toast.LENGTH_SHORT).show();
                        break;
                    }
                    //如果已存储sendBundle则可以跳转
                    if (null!=sendBundle){
                        //判断了当前绑定的Activity是否实现了该接口，如果实现了 则调用
                        if (getActivity() instanceof FSearchListener)
                        {
                            ((FSearchListener) getActivity()).onFSearchCommitClick(v,sendBundle);
                        }
                        break;
                    }
                }
        }
    }

    @Override
    public void onPause() {
        super.onPause();
        //隐藏软键盘
        MainActivity mainActivity= (MainActivity) getActivity();
        mainActivity.hideSoftInput(getView());
    }

    /**
     * onDestroyView中进行解绑操作
     */
    @SneakyThrows
    @Override
    public void onDestroyView() {
        super.onDestroyView();
        unbinder.unbind();//解绑butterknife视图
//        dbUtil.release();//释放资源
    }
}